/*
 *  main.h
 *  Particles
 *
 *  Created by Viehdorfer, Matt on 11/18/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */
#include <stdio.h>
#include <ctype.h>
#include <omp.h>       //OSX: XCode incorrectly reports an error here...just ignore it
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

#define _USE_MATH_DEFINES
#include <math.h>

#ifdef WIN32
#include <windows.h>
#include <Shlwapi.h>        //Filepath stuff
#include <atlstr.h>         //Filepath stuff
#include "Win/glew.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include "Win/glut.h"
#include "Win/glui.h"
#pragma warning(disable:4996)
#endif

#ifdef __APPLE__
#include <mach-o/dyld.h>	// _NSGetExecutablePath
#include <GLUI/glui.h>
#include <GLUT/glut.h>
#endif


#include "helpers.h"
//#include "particles.h"

// Max particles
#define NUMPARTICLES	1024
#define TIME_COUNT		30000
//#define TIME_COUNT		300

struct xyzw
{
	float x, y, z, w;
};

struct rgba
{
	float r, g, b, a;
};

const float startingPos[] = { 0, 0, 0 };

float randomArray[NUMPARTICLES];
struct xyzw points[NUMPARTICLES];
struct rgba colors[NUMPARTICLES];
struct xyzw hVel[NUMPARTICLES];

//#include <GLUI/glui.h>
//#include <GLUT/glut.h>


// Window Titles
const char *WINDOWTITLE = { "Particle System -- Matt Viehdorfer" };
const char *GLUITITLE   = { "User Interface Window" };


// GLUI true/false declarations
const int GLUITRUE  = { true  };
const int GLUIFALSE = { false };


// Escape key:
#define ESCAPE		0x1b


// Initial window size
const int INIT_WINDOW_SIZE = { 600 };


// Multiplication factors for input interaction:
//  (these are known from previous experience)
const float ANGFACT = { 1. };
const float SCLFACT = { 0.005f };


// Able to use the left mouse for either rotation or scaling
enum LeftButton
{
	ROTATE,
	SCALE
};


// Minimum scale factor
const float MINSCALE = { 0.05f };


// Active mouse buttons
const int LEFT   = { 4 };
const int MIDDLE = { 2 };
const int RIGHT  = { 1 };


// Which projection
enum Projections
{
	ORTHO,
	PERSP
};


// Which button
enum ButtonVals
{
	GO,
	RESET,
	QUIT
};


// Window background color (rgba)
const float BACKCOLOR[] = { 0., 0., 0., 0. };


// Color and line width for the axes
const GLfloat AXES_COLOR[] = { 1., .5, 0. };
const GLfloat AXES_WIDTH   = { 3. };


// Fog parameters
const GLfloat FOGCOLOR[4] = { .0, .0, .0, 1. };
const GLenum  FOGMODE     = { GL_LINEAR };
const GLfloat FOGDENSITY  = { 0.30f };
const GLfloat FOGSTART    = { 1.5 };
const GLfloat FOGEND      = { 4. };

// Non-constant global variables:
int	ActiveButton;		// current button that is down
//int	Debug;				// ON means print debug info
GLUI *	Glui;			// instance of glui window
int	GluiWindow;			// the glut id for the glui window
int	LeftButton;			// either ROTATE or SCALE
int	MainWindow;			// window id for main graphics window
GLfloat	RotMatrix[4][4];	// set by glui rotation widget
float	Scale, Scale2;		// scaling factors
int	WhichProjection;	// ORTHO or PERSP
int	Xmouse, Ymouse;		// mouse values
float	Xrot, Yrot;		// rotation angles in degrees
float	TransXYZ[3];	// set by glui translation widgets
GLuint		hPobj;
GLuint		hCobj;

double compTimes[TIME_COUNT];
int compNum = 0;
double time0, time1;
double startTime, endTime;

// Function prototypes
void	Animate( void );
void	Buttons( int );
void	Display( void );
void	DoRasterString( float, float, float, char * );
void	DoStrokeString( float, float, float, float, char * );
float	ElapsedSeconds( void );
void	InitGlui( void );
void	InitGraphics( void );
void	InitLists( void );
void	Keyboard( unsigned char, int, int );
void	MouseButton( int, int, int, int );
void	MouseMotion( int, int );
void	Reset( void );
void	Resize( int, int );
void	Visibility( int );
void	Quit();
void	LogTimeOut();

//function prototypes
float myRandom(int i, float low, float high);
float adjustVelocity(int i, float low, float high);
float adjustAccel(int i, float low, float high);
int randomColor(int min, int max);
void updateParticle(int index);
void genParticle(int index, bool nonMoveAttrib);
void initParticles();